home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume19 / fbm / part04 < prev    next >
Encoding:
Internet Message Format  |  1989-06-08  |  55.4 KB

  1. Subject:  v19i050:  FBM, image manipulation library, Part04/08
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Michael.Mauldin@NL.CS.CMU.EDU
  7. Posting-number: Volume 19, Issue 50
  8. Archive-name: fbm/part04
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of archive 4 (of 8)."
  17. # Contents:  fbhalf.c fbm.1 fbm2pod.c flblue.c flextr.c flgife.c
  18. #   flpbm.c flrot.c flshrp.c
  19. # Wrapped by rsalz@fig.bbn.com on Fri Jun  9 08:38:25 1989
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f 'fbhalf.c' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'fbhalf.c'\"
  23. else
  24. echo shar: Extracting \"'fbhalf.c'\" \(6203 characters\)
  25. sed "s/^X//" >'fbhalf.c' <<'END_OF_FILE'
  26. X/*****************************************************************
  27. X * fbhalf.c: FBM Library 0.93 (Beta test) 03-May-89  Michael Mauldin
  28. X *
  29. X * Copyright (C) 1989 by Michael Mauldin.  Permission is granted to
  30. X * use this file in whole or in part provided that you do not sell it
  31. X * for profit and that this copyright notice is retained unchanged.
  32. X *
  33. X * fbhalf.c: Take an 8bit gray image, resize it to a maximum total
  34. X *          number of pixels, optionally sharpen it with a digital
  35. X *          Laplacian filter, and halftone it using one of three
  36. X *          standard algorithms.  Output the result in PBM format.
  37. X *
  38. X * USAGE
  39. X *    % fbhalf [ -args ]  [ size ] < 8bit > 1bit
  40. X *
  41. X *    size    Choose a width and height as large as possible so that
  42. X *        width is a factor of 8 and width*height <= size (default
  43. X *        is width and height of original 8bit file, ignoring aspect
  44. X *        ratio).
  45. X *
  46. X *    -f    Do Floyd-Steinberg halftoning (the default algorithm)
  47. X *    -b<int>    Do Blue noise halftoning (-b50 or 50% noise is default)
  48. X *    -c<int>    Do Constained average halftoning (-c4 is the default)
  49. X *    -s<int>    Sharpen the image with a given beta (-s2.0 is default)
  50. X *    -t<int>    Use a threshhold of <int> to halftone (127 is default)
  51. X *
  52. X *    -C<int>,-N<int>
  53. X *        Clean up image by flipping isolated pixels.  A pixel is
  54. X *        isolated if there are fewer than C like pixels in the
  55. X *        nearby NxN square.
  56. X *
  57. X * EDITLOG
  58. X *    LastEditDate = Wed May  3 21:50:43 1989 - Michael Mauldin
  59. X *    LastFileName = /usr2/mlm/src/misc/fbm/fbhalf.c
  60. X *
  61. X * HISTORY
  62. X * 03-May-89  Michael Mauldin (mlm) at Carnegie Mellon University
  63. X *    Beta release (version 0.93) mlm@cs.cmu.edu
  64. X *
  65. X *  8-Sep-88  Michael Mauldin (mlm) at Carnegie-Mellon University
  66. X *    Created.
  67. X *****************************************************************/
  68. X
  69. X# include <stdio.h>
  70. X# include <math.h>
  71. X# include "fbm.h"
  72. X
  73. X# define USAGE\
  74. X"Usage: fbhalf [ -fbct<parm> ] [-s<sharpen> ] [ -<type> ]\n\
  75. X              [ -C<clean> -N<nbr>] [ size ] < 8bit > 1bit"
  76. X
  77. X#ifndef lint
  78. Xstatic char *fbmid =
  79. X    "$FBM fbhalf.c <0.93> 03-May-89  (C) 1989 by Michael Mauldin$";
  80. X#endif
  81. X
  82. Xmain (argc, argv)
  83. Xchar *argv[];
  84. X{ int w, h, ow = -1, oh = -1, size = -1, alg = 'b';
  85. X  int clean = -1, nbr = 5, outtype = DEF_1BIT;
  86. X  double beta = -1e9, parm = -1e9;
  87. X  char *title, *credits;
  88. X  FBM input, resized, sharpened, halftoned, cleaned, *image;
  89. X
  90. X  /* Clear pointers */
  91. X  input.bm     = input.cm     = (unsigned char *) NULL;
  92. X  resized.bm   = resized.cm   = (unsigned char *) NULL;
  93. X  sharpened.bm = sharpened.cm = (unsigned char *) NULL;
  94. X  halftoned.bm = halftoned.cm = (unsigned char *) NULL;
  95. X  cleaned.bm   = cleaned.cm   = (unsigned char *) NULL;
  96. X
  97. X  if (read_bitmap (&input, (char *) NULL))
  98. X  {
  99. X    if (input.hdr.bits != 8 || input.hdr.physbits != 8)
  100. X    { fprintf (stderr,
  101. X           "Can't handle images with %d bits and %d physbits per pixel\n",
  102. X           input.hdr.bits, input.hdr.physbits);
  103. X      exit (1);
  104. X    }
  105. X
  106. X    if (input.hdr.title[0]) title = input.hdr.title;
  107. X    if (input.hdr.credits[0]) credits = input.hdr.credits;
  108. X
  109. X    /* Get the options */
  110. X    while (--argc > 0 && (*++argv)[0] == '-')
  111. X    { while (*++(*argv))
  112. X      { switch (**argv)
  113. X        { case 's':    if (argv[0][1]) { beta = atof (*argv+1); SKIPARG; }
  114. X            else        beta = 2.0;
  115. X            break;
  116. X            
  117. X      case 'f':    alg = 'f'; parm = 0.0; break;
  118. X            
  119. X      case 'b':    alg = 'b';
  120. X            if (argv[0][1])    { parm = atof (*argv+1); SKIPARG; }
  121. X            break;
  122. X            
  123. X      case 'c':    alg = 'c';
  124. X            if (argv[0][1])    { parm = atof (*argv+1); SKIPARG; }
  125. X            break;
  126. X            
  127. X      case 't':    alg = 't';
  128. X            if (argv[0][1])    { parm = atoi (*argv+1); SKIPARG; }
  129. X            else        { parm = 127; }
  130. X            break;
  131. X            
  132. X      case 'C':    if (argv[0][1])    { clean = atoi (*argv+1); SKIPARG; }
  133. X              else        { clean = 10; }
  134. X            break;
  135. X            
  136. X      case 'N':    if (argv[0][1])    { nbr = atoi (*argv+1); SKIPARG; }
  137. X              else        { nbr = 5; }
  138. X            
  139. X            if (clean < 0)    { clean = 10; }
  140. X            break;
  141. X            
  142. X      case 'A':    outtype = FMT_ATK; break;
  143. X      case 'B':    outtype = FMT_FACE; break;
  144. X      case 'F':    outtype = FMT_FBM; break;
  145. X      case 'G':    outtype = FMT_GIF; break;
  146. X      case 'I':    outtype = FMT_IFF; break;
  147. X      case 'L':    outtype = FMT_LEAF; break;
  148. X      case 'M':    outtype = FMT_MCP; break;
  149. X      case 'P':    outtype = FMT_PBM; break;
  150. X      case 'S':    outtype = FMT_SUN; break;
  151. X      case 'T':    outtype = FMT_TIFF; break;
  152. X      case 'X':    outtype = FMT_X11; break;
  153. X      case 'Z':    outtype = FMT_PCX; break;
  154. X
  155. X
  156. X      default:    fprintf (stderr, "%s", USAGE);
  157. X            exit (1);
  158. X        }
  159. X      }
  160. X    }
  161. X    
  162. X    if (argc > 0)    size = atoi (argv[0]);
  163. X
  164. X    /* Default parms for algorithms */
  165. X    if (parm <= -1e9)
  166. X    { if      (alg == 'b') parm = 50.0;
  167. X      else if (alg == 'c') parm = 4.0;
  168. X      else if (alg == 't') parm = 128.0;
  169. X    }
  170. X
  171. X    /* Determine output height & width (oh*ow <= size) */
  172. X    h = input.hdr.rows;
  173. X    w = input.hdr.cols;
  174. X
  175. X    if (size < 0)
  176. X    { oh = h; ow = w; }
  177. X    else
  178. X    { ow = sqrt ((double) size * w / (h * input.hdr.aspect));
  179. X      ow &= ~7;            /* Make width multiple of 8 */
  180. X      oh = ow * input.hdr.aspect * h / w;
  181. X    }
  182. X
  183. X    fprintf (stderr,
  184. X         "Halftone \"%s\" size [%dx%d] => %d pixels\n",
  185. X         input.hdr.title[0] ? input.hdr.title : "(untitled)",
  186. X         ow, oh, ow*oh);
  187. X
  188. X    /* Start with image in variable 'input' */
  189. X    image = &input;
  190. X
  191. X    /* If necessary, resize it */
  192. X    if (w != ow || h != oh)
  193. X    { if (extract_fbm (image, &resized, 0, 0, w, h, ow, oh, title, credits))
  194. X      { free_fbm (image);
  195. X    image = &resized;
  196. X      }
  197. X      else
  198. X      { exit (1); }
  199. X    }
  200. X
  201. X    /* Sharpen the image if requested */    
  202. X    if (beta > -1e9)
  203. X    { if (sharpen_fbm (image, &sharpened, beta))
  204. X      { free_fbm (image);
  205. X    image = &sharpened;
  206. X      }
  207. X      else
  208. X      { exit (1); }
  209. X    }
  210. X    
  211. X    /* Now use the appropriate algorithm to halftone it */
  212. X    switch (alg)
  213. X    { case 'b':    bluenoise_fbm (image, &halftoned, parm); break;
  214. X      case 'c': constravg_fbm (image, &halftoned, parm); break;
  215. X      case 't': thesh_fbm (image, &halftoned, (int) parm); break;
  216. X      default:    floyd_fbm (image, &halftoned);
  217. X    }
  218. X
  219. X    /* free_fbm (image); */
  220. X    image = &halftoned;
  221. X
  222. X    if (clean >= 0)
  223. X    { if (!clean_fbm (image, &cleaned, clean, 1, nbr))
  224. X      { exit (1); }
  225. X
  226. X      free_fbm (image);
  227. X      image = &cleaned;      
  228. X    }
  229. X
  230. X    if (write_bitmap (image, stdout, outtype)) exit (0);
  231. X  }
  232. X  
  233. X  exit (1);
  234. X}
  235. END_OF_FILE
  236. if test 6203 -ne `wc -c <'fbhalf.c'`; then
  237.     echo shar: \"'fbhalf.c'\" unpacked with wrong size!
  238. fi
  239. # end of 'fbhalf.c'
  240. fi
  241. if test -f 'fbm.1' -a "${1}" != "-c" ; then 
  242.   echo shar: Will not clobber existing file \"'fbm.1'\"
  243. else
  244. echo shar: Extracting \"'fbm.1'\" \(6127 characters\)
  245. sed "s/^X//" >'fbm.1' <<'END_OF_FILE'
  246. X.TH FBM 1 07-Mar-89
  247. X.CM 3
  248. X.SH NAME
  249. Xfbm \- Fuzzy pixmap manipulation (Sun, GIF, IFF, HAM, PCX, PBM, FBM, PostScript, rasters, bitmaps, pixmaps)
  250. X.SH SYNOPSIS
  251. X.nf
  252. Xclr2gray  Convert color to grayscale
  253. Xfbcat     Copy image (used for format conversion)
  254. Xfbclean   Flip isolated pixels (clean image)
  255. Xfbedge    Compute derivative image (edge detection)
  256. Xfbext     Extract region, resize, change aspect ratio
  257. Xfbhalf    Halftone grayscale image (Blue noise, Floyd-Steinberg, etc)
  258. Xfbham     Convert 24 bit color to Amiga HAM mode
  259. Xfbhist    Compute histogram
  260. Xfbinfo    Dump image header
  261. Xfbm2pod   Convert grayscale image to Diablo graphics (!)
  262. Xfbm2tga   Convert FBM to Targa format
  263. Xfbmask    Set region to gray value
  264. Xfbnorm    Normalize image intensity / increase contrast
  265. Xfbps      Convert greyscale to PostScript
  266. Xfbquant   Color quantization (24 bit to 8..256 colors) Mod. Heckbert
  267. Xfbrot     Rotate 90, 180, or 270 degrees
  268. Xfbsample  Sample a 1bit file to produce an 8bit file
  269. Xfbsharp   Sharpen (edge enhancement) by digital Laplacian
  270. Xgray2clr  Add a "gray" colormap to a grayscale image
  271. Xidiff     (and udiff) convert raw byte stream into byte-by-byte difference
  272. Xpbm2ps    Convert PBM file to PostScript
  273. Xpbmtitle  Add a title to a PBM file
  274. Xpic2fbm   Convert PIC format to FBM
  275. Xqrt2fbm   Convert QRT raytracer output to FBM
  276. Xraw2fbm   Convert raw file to FBM format (eg: Amiga Digiview files)
  277. Xtga2fbm   Convert Targa format to FBM format
  278. X.fi
  279. X.SH DESCRIPTION
  280. X.PP
  281. XThe Fuzzy Pixmap package (FBM) is a collection of routines for the
  282. Xmanipulation and conversion of images from and to a variety of file
  283. Xformats.  
  284. X.SH FILE FORMATS
  285. X.PP
  286. XIn general each routine can read any type of file format (file type is
  287. Xdetermined by examining the magic numbers).  Files that are compressed
  288. Xwith the Lempel-Ziv 'compress' program are automatically uncompressed
  289. Xwhere possible.
  290. X.sp
  291. XOutput file format is specified by an upper case letter in the argument
  292. Xlist.  Each site has a separate default (defined in fbm.h) for 8bit and
  293. X1bit images.  The following upper
  294. Xcase letters are assigned (not all are handled, yet):
  295. X.sp
  296. X.TP
  297. X.BR -A
  298. X.I andrew toolkit
  299. XCMU specific format (not implemented, if at CMU, use 'bmcv' to convert).
  300. X.TP
  301. X.BR -B
  302. X.I face
  303. Xformat, as used by Bennet Yee's
  304. X.I face
  305. Xprogram at CMU. His 'bmcv' program can convert to a number of useful
  306. Xformats.
  307. X.TP
  308. X.BR -F
  309. X.I FBM
  310. Xformat (by default, the default).  You are guaranteed not
  311. Xto lose information by specifying FBM as the default.
  312. X.TP
  313. X.BR -G
  314. X.I GIF
  315. XCompuserve GIF format.  GIF support by David Koblas and David Rowley.
  316. XOn input, the aspect ratio is guessed from the size (for example,
  317. X320x200 and 640x400 images are assumed to have an aspect ratio of 1.2).
  318. XFor unknown sizes, an aspect ratio of 1.0 is assumed.  fbcat can
  319. Xoverride the aspect ratio, if you know the actual value.
  320. X.TP
  321. X.BR -I
  322. X.I IFF
  323. Xformat, interleaved bitmaps (ILBM), used mainly by Amigas (from ELArts).
  324. XTo output HAM mode, create a 24 bit color image and use the fbham(1)
  325. Xcommand to convert it to a 6 plane IFF ILBM HAM mode file.
  326. X.TP
  327. X.BR -L
  328. X.I InterLeaf
  329. Xbitmap format for inclusion in InterLeaf documents (not yet supported).
  330. X.TP
  331. X.BR -M
  332. X.I MacPaint
  333. Xformat (not yet supported).
  334. X.TP
  335. X.BR -P
  336. X.I PBM
  337. XJef Poskanzer's bitmap format.  His pbm(1) package can convert this to
  338. Xa number of useful formats.
  339. X.TP
  340. X.BR -S
  341. X.I sun
  342. Xrasterfiles.  Code does not require any Sun libraries to read or write
  343. XSun format.
  344. X.TP
  345. X.BR -T
  346. X.I TIFF
  347. Xformat, as used by NeXT machines and many scanners (not yet supported).
  348. X.TP
  349. X.BR -Z
  350. X.I ZSoft's PCX
  351. Xformat, as used on IBM PCs (read support only).
  352. X.PP
  353. X.SH OPTIONS
  354. X.PP
  355. XSome options are common, and an attempt has been made to keep the
  356. Xletters the same throughout, although the same letter may mean
  357. Xsomething else in some circumstances.
  358. X.TP
  359. X.BR -a
  360. X.I aspect ratio,
  361. Xsome rasters (like Amiga and IBM PC images) have pixels that are
  362. X"taller" than they are wide.  For example, a standard TV image is 4/3
  363. Xwider than it is tall.  A "standard" screen that is 320 by 200 is
  364. Xsquashed so that it appears normal when displayed as though it were 320
  365. Xby 240 (and 240 / 200 gives a 1.2 aspect ratio).
  366. X.sp
  367. XOn some programs, like 
  368. X.I raw2fbm & fbcat,
  369. Xthe
  370. X.B -a
  371. Xoption specifies the aspect ratio of the input (for GIF and raw bitmaps
  372. Xthe default is 1.2).  Other programs (like
  373. X.I fbext)
  374. Xuse this parameter as the desired output ratio.
  375. XFinally, some programs assume specific ratios (usually 1, although
  376. X.fpm2pod
  377. Xassumes 1.25 for output).
  378. X.TP
  379. X.BR -w, -h
  380. X.I width
  381. Xand
  382. X.I height,
  383. Xspecifies the actual or desired width and height.
  384. X.TP
  385. X.BR -t'title'
  386. X.I title,
  387. Xspecify a character string (up to 80 characters) to describe the image.
  388. XThe default is no title.
  389. X.TP
  390. X.BR -c'credits'
  391. X.I credits or subtitle,
  392. Xspecify a second character string (up to 80 characters) to describe the
  393. Ximage.  The default is no credit string.
  394. X.TP
  395. X.BR -s
  396. X.I size
  397. Xor
  398. X.I sharpen
  399. Xhalftoning programs use
  400. X.B -s
  401. Xto specifiy the amount of sharpening (0=none, values up to 5 look
  402. Xreasonable, higher values generate may be too extreme).  The extraction
  403. Xprogram fbext(1) uses
  404. X.B -s
  405. Xto mean the output size in total number of pixels.
  406. X.sp
  407. XThat's what comes of using one letter argument names.
  408. X.PP
  409. X.SH SEE ALSO
  410. Xclr2gray(1),
  411. Xfbcat(1),
  412. Xfbclean(1),
  413. Xfbedge(1),
  414. Xfbext(1),
  415. Xfbhalf(1),
  416. Xfbham(1),
  417. Xfbhist(1),
  418. Xfbinfo(1),
  419. Xfbm2pod(1),
  420. Xfbmask(1),
  421. Xfbnorm(1),
  422. Xfbps(1),
  423. Xfbquant(1),
  424. Xfbrot(1),
  425. Xfbsample(1),
  426. Xfbsharp(1),
  427. Xgray2clr(1),
  428. Xidiff(1),
  429. Xpbm2ps(1),
  430. Xpbmtitle(1),
  431. Xraw2fbm(1),
  432. Xas well as pbm(1) for PBM routines.
  433. X.SH BUGS
  434. XNone known.
  435. X.SH HISTORY
  436. XCopyright (c) 1989 by Michael L. Mauldin.  
  437. XPermission is granted to use this program in whole or in part provided
  438. Xthat you do not sell it for profit and that this copyright notice is
  439. Xretained unchanged.  User contributed software may also be subject to
  440. Xother copyright restrictions as noted in each individual source file.
  441. X.TP
  442. X20-May-89  Michael L. Mauldin at Carnegie Mellon University
  443. XBeta release (version 0.94) mlm@cs.cmu.edu. User contributed software
  444. Xincludes
  445. X.nf
  446. X    C. Harald Koch    fbham
  447. X    Butler Hines    qrt2fbm
  448. X    Ian MacPhedran    tga2fbm, fbm2tga, pic2fbm
  449. X.fi
  450. X.TP
  451. X07-Mar-89  Michael L. Mauldin at Carnegie Mellon University
  452. XBeta release (version 0.9) mlm@cs.cmu.edu
  453. END_OF_FILE
  454. if test 6127 -ne `wc -c <'fbm.1'`; then
  455.     echo shar: \"'fbm.1'\" unpacked with wrong size!
  456. fi
  457. # end of 'fbm.1'
  458. fi
  459. if test -f 'fbm2pod.c' -a "${1}" != "-c" ; then 
  460.   echo shar: Will not clobber existing file \"'fbm2pod.c'\"
  461. else
  462. echo shar: Extracting \"'fbm2pod.c'\" \(5563 characters\)
  463. sed "s/^X//" >'fbm2pod.c' <<'END_OF_FILE'
  464. X/*****************************************************************
  465. X * fbm2pod.c: FBM Library 0.9 (Beta test) 07-Mar-89  Michael Mauldin
  466. X *
  467. X * Copyright (C) 1989 by Michael Mauldin.  Permission is granted to
  468. X * use this file in whole or in part provided that you do not sell it
  469. X * for profit and that this copyright notice is retained unchanged.
  470. X *
  471. X * fbm2pod.c: Take an 8bit gray image, resize it to a maximum total
  472. X *          number of pixels, optionally sharpen it with a digital
  473. X *          Laplacian filter, and halftone it using one of three
  474. X *          standard algorithms.  Output the result in Diablo
  475. X *          graphics format.
  476. X *
  477. X * USAGE
  478. X *    % fbm2pod [ -args ]  [ size ] < foo.fbm > foo.pod
  479. X *
  480. X *    size    Choose a width and height as large as possible so that
  481. X *        width is a factor of 8 and width*height <= size (default
  482. X *        is width and height of original 8bit file, ignoring aspect
  483. X *        ratio).
  484. X *
  485. X *    -f    Do Floyd-Steinberg halftoning (the default algorithm)
  486. X *    -bNNN    Do Blue noise halftoning (-b50 or 50% noise is default)
  487. X *    -cNNN    Do Constained average halftoning (-c4 is the default)
  488. X *    -sNNN    Sharpen the image with a given beta (-s2.0 is default)
  489. X *
  490. X * EDITLOG
  491. X *    LastEditDate = Wed Mar  8 14:22:04 1989 - Michael Mauldin
  492. X *    LastFileName = /usr2/mlm/src/misc/fbm/fbm2pod.c
  493. X *
  494. X * HISTORY
  495. X * 07-Mar-89  Michael Mauldin (mlm) at Carnegie Mellon University
  496. X *    Beta release (version 0.9) mlm@cs.cmu.edu
  497. X *
  498. X *  8-Sep-88  Michael Mauldin (mlm) at Carnegie-Mellon University
  499. X *    Created.
  500. X *****************************************************************/
  501. X
  502. X# include <stdio.h>
  503. X# include <math.h>
  504. X# include "fbm.h"
  505. X
  506. X# define PODASPECT 1.25
  507. X
  508. X# define USAGE \
  509. X"Usage: fbm2pod [ -fbc<parm> ] [-s<sharpen> ] [ size ] < 8bit > pod"
  510. X
  511. X#ifndef lint
  512. Xstatic char *fbmid =
  513. X    "$FBM fbm2pod.c <0.9> 07-Mar-89  (C) 1989 by Michael Mauldin$";
  514. X#endif
  515. X
  516. Xmain (argc, argv)
  517. Xchar *argv[];
  518. X{ int w, h, ow = -1, oh = -1, size = -1, alg = 'b';
  519. X  double beta = -1e9, parm = -1e9;
  520. X  char *title;
  521. X  FBM input, resized, sharpened, output, *image;
  522. X
  523. X  /* Clear the memory pointers so alloc_fbm won't be confused */
  524. X  input.cm     = input.bm     = (unsigned char *) NULL;
  525. X  resized.cm   = resized.bm   = (unsigned char *) NULL;
  526. X  sharpened.cm = sharpened.bm = (unsigned char *) NULL;
  527. X  output.cm    = output.bm    = (unsigned char *) NULL;
  528. X
  529. X  /* Read the image */
  530. X  if (read_bitmap (&input, (char *) NULL))
  531. X  {
  532. X    if (input.hdr.bits != 8 || input.hdr.physbits != 8)
  533. X    { fprintf (stderr,
  534. X           "Can't handle images with %d bits and %d physbits per pixel\n",
  535. X           input.hdr.bits, input.hdr.physbits);
  536. X      exit (1);
  537. X    }
  538. X
  539. X    if (input.hdr.title[0]) title = input.hdr.title;
  540. X
  541. X    /* Get the options */
  542. X    while (--argc > 0 && (*++argv)[0] == '-')
  543. X    { while (*++(*argv))
  544. X      { switch (**argv)
  545. X        { case 's':    if (argv[0][1]) { beta = atof (*argv+1); SKIPARG; }
  546. X            else        beta = 2.0;
  547. X            break;
  548. X            
  549. X      case 'f':    alg = 'f'; break;
  550. X            
  551. X      case 'b':    alg = 'b';
  552. X            if (argv[0][1])    { parm = atof (*argv+1); SKIPARG; }
  553. X            break;
  554. X            
  555. X      case 'c':    alg = 'c';
  556. X            if (argv[0][1])    { parm = atof (*argv+1); SKIPARG; }
  557. X            break;
  558. X            
  559. X      default:    fprintf (stderr, "%s", USAGE);
  560. X            exit (1);
  561. X        }
  562. X      }
  563. X    }
  564. X    
  565. X    if (argc > 0)    size = atoi (argv[0]);
  566. X
  567. X    /* Default parms for algorithms */
  568. X    if (parm <= -1e9)
  569. X    { if      (alg == 'b') parm = 50.0;
  570. X      else if (alg == 'c') parm = 4.0;
  571. X    }
  572. X
  573. X    /* Determine output height & width (oh*ow <= size) */
  574. X    h = input.hdr.rows;
  575. X    w = input.hdr.cols;
  576. X
  577. X    if (size < 0)
  578. X    { oh = h; ow = w; }
  579. X    else
  580. X    { ow = sqrt ((double) size * w / (h * input.hdr.aspect / PODASPECT));
  581. X      ow &= ~7;            /* Make width multiple of 8 */
  582. X      oh = ow * input.hdr.aspect/PODASPECT * h / w;
  583. X    }
  584. X
  585. X    fprintf (stderr,
  586. X         "Halftone \"%s\" size [%dx%d] => %d pixels\n",
  587. X         input.hdr.title[0] ? input.hdr.title : "(untitled)",
  588. X         ow, oh, ow*oh);
  589. X
  590. X    /* Start with image in variable 'input' */
  591. X    image = &input;
  592. X
  593. X    /* If necessary, resize it */
  594. X    if (w != ow || h != oh)
  595. X    { if (extract_fbm (&input, &resized, 0, 0, w, h, ow, oh, title, (char *) NULL))
  596. X      { image = &resized; }
  597. X      else
  598. X      { exit (1); }
  599. X    }
  600. X
  601. X    /* Sharpen the image if requested */    
  602. X    if (beta > -1e9)
  603. X    { if (sharpen_fbm (image, &sharpened, beta))
  604. X      { image = &sharpened; }
  605. X      else
  606. X      { exit (1); }
  607. X    }
  608. X    
  609. X    /* Now use the appropriate algorithm to halftone it */
  610. X    switch (alg)
  611. X    { case 'b':    bluenoise_fbm (image, &output, parm); break;
  612. X      case 'c': constravg_fbm (image, &output, parm); break;
  613. X      default:    floyd_fbm (image, &output);
  614. X    }
  615. X
  616. X    if (write_pod (&output, stdout)) exit (0);
  617. X  }
  618. X  
  619. X  exit (1);
  620. X}
  621. X
  622. X/****************************************************************
  623. X * write_pod: Write out a binary bitmap as a Diablo file, for use
  624. X *          by the podtype or mp programs.
  625. X ****************************************************************/
  626. X
  627. X# define FF "\014"
  628. X# define LF "\012"
  629. X# define CR "\015"
  630. X# define GON    "\033\037\005\033\036\003"
  631. X# define GOFF    "\033\037\015\033\036\011"
  632. X# define ABSTAB "\033\011"
  633. X# define STARTCOL 10
  634. X
  635. Xwrite_pod (image, stream)
  636. XFBM *image;
  637. XFILE *stream;
  638. X{ register int i, j, h, w;
  639. X
  640. X  h = image->hdr.rows;
  641. X  w = image->hdr.cols;
  642. X
  643. X  /* Bracket commands with form feeds (for podtype) */
  644. X  fprintf (stream, "%s%s%s", FF, CR, GOFF);
  645. X  
  646. X  for (j=0; j<h; j++)
  647. X  { fprintf (stream, "%s%c%s", ABSTAB, STARTCOL+1, GON);
  648. X    for (i=0; i<w; i++)
  649. X    { putchar (image->bm[j*w + i] ? ' ' : '.'); }
  650. X    fprintf (stream, "%s%s%s", LF, GOFF, CR);
  651. X    
  652. X  }
  653. X  
  654. X  fprintf (stream, "%s", FF);
  655. X  
  656. X  return (1);
  657. X}
  658. END_OF_FILE
  659. if test 5563 -ne `wc -c <'fbm2pod.c'`; then
  660.     echo shar: \"'fbm2pod.c'\" unpacked with wrong size!
  661. fi
  662. # end of 'fbm2pod.c'
  663. fi
  664. if test -f 'flblue.c' -a "${1}" != "-c" ; then 
  665.   echo shar: Will not clobber existing file \"'flblue.c'\"
  666. else
  667. echo shar: Extracting \"'flblue.c'\" \(5880 characters\)
  668. sed "s/^X//" >'flblue.c' <<'END_OF_FILE'
  669. X/*****************************************************************
  670. X * flblue.c: FBM Library 0.94 (Beta test) 20-May-89  Michael Mauldin
  671. X *
  672. X * Copyright (C) 1989 by Michael Mauldin.  Permission is granted to
  673. X * use this file in whole or in part provided that you do not sell it
  674. X * for profit and that this copyright notice is retained unchanged.
  675. X *
  676. X * flblue.c: Blue noise dithering
  677. X *
  678. X * CONTENTS
  679. X *    bluenoise_fbm (input, output, noiselevel)
  680. X *
  681. X * EDITLOG
  682. X *    LastEditDate = Sat May 20 19:06:08 1989 - Michael Mauldin
  683. X *    LastFileName = /usr2/mlm/src/misc/fbm/flblue.c
  684. X *
  685. X * HISTORY
  686. X * 20-May-89  Michael Mauldin (mlm) at Carnegie Mellon University
  687. X *    Bug fix from Dave Cohrs <dave@cs.wisc.edu>
  688. X *
  689. X * 07-Mar-89  Michael Mauldin (mlm) at Carnegie Mellon University
  690. X *    Beta release (version 0.9) mlm@cs.cmu.edu
  691. X *
  692. X * 12-Nov-88  Michael Mauldin (mlm) at Carnegie-Mellon University
  693. X *    Created.
  694. X *****************************************************************/
  695. X
  696. X# include <stdio.h>
  697. X# include <math.h>
  698. X# include <ctype.h>
  699. X# include "fbm.h"
  700. X
  701. X/*****************************************************************
  702. X * bluenoise_fbm:  Do Floyd-Steinberg halftoning with serpentine
  703. X *           raster and 'noiselevel' random weights.
  704. X *           (noise level runs from 0 to 100 percent)
  705. X *
  706. X * REFERENCES
  707. X *    Digital Halftoning, by Robert Ulichney (1986 MIT Press)
  708. X *****************************************************************/
  709. X
  710. X# define RAND(RN) (((seed = 1103515245 * seed + 12345) >> 12) % (RN))
  711. X# define INITERR(X,Y) \
  712. X    (((int) X) - (((int) Y)?WHITE:BLACK) + ((WHITE/2)-((int) X))/2)
  713. X
  714. X#ifndef lint
  715. Xstatic char *fbmid =
  716. X    "$FBM flblue.c <0.94> 20-May-89  (C) 1989 by Michael Mauldin$";
  717. X#endif
  718. X
  719. Xbluenoise_fbm (input, output, noiselevel)
  720. XFBM *input, *output;
  721. Xdouble noiselevel;
  722. X{ register unsigned char *bmp, *obm;
  723. X  register unsigned seed = 0;
  724. X  register int i, j, rowlen, gray, error, w, h, den, outrow;
  725. X  int w1, w3, w5, w7, smrange, lgrange, smnoise, lgnoise;
  726. X  int *eerr, *oerr;
  727. X
  728. X  if (input->hdr.planes != 1)
  729. X  { fprintf (stderr, "bluenoise_fbm: can't halftone color images\n");
  730. X    return (0);
  731. X  }
  732. X
  733. X  fprintf (stderr, "Blue noise, %1.2lf%% weights\n", noiselevel);
  734. X
  735. X  /* Allocate output */
  736. X  free_fbm (output);
  737. X  output->hdr = input->hdr;
  738. X  output->hdr.bits = 1;
  739. X  output->hdr.physbits = 8;
  740. X  outrow = 16 * ((input->hdr.cols + 15) / 16); /* Pad to even byte boundary */
  741. X  output->hdr.rowlen = outrow;
  742. X  output->hdr.plnlen = outrow*output->hdr.rows;
  743. X  alloc_fbm (output);
  744. X
  745. X  w = input->hdr.cols;
  746. X  h = input->hdr.rows;
  747. X  rowlen = input->hdr.rowlen;
  748. X  
  749. X  /* Allocate space for error arrays */
  750. X  eerr = (int *) malloc ((unsigned) w * sizeof (*eerr));
  751. X  oerr = (int *) malloc ((unsigned) w * sizeof (*oerr));
  752. X  for (i=0; i<w; i++) eerr[i] = oerr[i] = 0;
  753. X
  754. X    /* The left border */
  755. X  error = 0;
  756. X  for (j=0; j<h; j++)
  757. X  { register int thresh = (WHITE/2 + RAND (129) - 64);
  758. X
  759. X    gray = input->bm[j*rowlen] + error;
  760. X    den = gray > thresh ? WHITE : BLACK;
  761. X    error = gray - den;
  762. X    output->bm[j*outrow] = den;
  763. X  }
  764. X
  765. X  /* The right border */
  766. X  error = 0;
  767. X  for (j=0; j<h; j++)
  768. X  { register int thresh = (WHITE/2 + RAND (129) - 64);
  769. X
  770. X    gray = input->bm[j*rowlen + (w-1)] + error;
  771. X    den = gray > thresh ? WHITE : BLACK;
  772. X    error = gray - den;
  773. X    output->bm[j*outrow + (w-1)] = den;
  774. X  }
  775. X
  776. X  /* The top border */
  777. X  error = 0;
  778. X  for (i=0; i<w; i++)
  779. X  { register int inp = input->bm[i], thresh = (WHITE/2 + RAND (129) - 64);
  780. X
  781. X    gray = inp + error;
  782. X    den = gray > thresh ? WHITE : BLACK;
  783. X    error = gray - den;
  784. X    output->bm[i] = den;
  785. X    eerr[i] = INITERR (inp, den);
  786. X  }
  787. X
  788. X  /*
  789. X   * Now process the interior bits
  790. X   *
  791. X   *  Weights:            1+n1  5+n5  3-n1
  792. X   *                7-n5    *
  793. X   *
  794. X   * n1 and n5 are random noise from -0.5 to 0.5 and -2.5 to 2.5
  795. X   */
  796. X   
  797. X  smrange = 2000 * noiselevel/100.0; smrange += 1;
  798. X  lgrange = 10000 * noiselevel/100.0; lgrange += 1;
  799. X  
  800. X# ifdef DEBUG
  801. X  fprintf (stderr, "Blue noise level %6.2lf (small %d..%d, large %d..%d)\n",
  802. X      noiselevel, -(smrange/2), smrange/2, -(lgrange/2), lgrange/2);
  803. X# endif
  804. X
  805. X  for (j=1; j<h; j++)
  806. X  { bmp = &input->bm[j*rowlen];
  807. X    obm = &output->bm[j*outrow];
  808. X
  809. X    if (j&1)                /* Odd rows */
  810. X    { oerr[0] = INITERR (bmp[0], obm[0]);
  811. X
  812. X      for (i=1; i<w-1; i++)
  813. X      { /* Set random weights */
  814. X    w1 = 1000; w3 = 3000; w5 = 5000; w7 = 7000;
  815. X  
  816. X    smnoise = RAND (smrange) - smrange/2;
  817. X    w1 += smnoise; w3 -= smnoise;
  818. X  
  819. X    lgnoise = RAND (lgrange) - lgrange/2;
  820. X    w5 += lgnoise; w7 -= lgnoise;
  821. X  
  822. X    error =  (w1 * eerr[i-1] +
  823. X          w5 * eerr[i] +
  824. X          w3 * eerr[i+1] +
  825. X          w7 * oerr[i-1]) / 16000;
  826. X    gray = bmp[i] + error;
  827. X  
  828. X# ifdef DEBUG
  829. X    if (j>10 && j<14 && i>40 && i<44)
  830. X    { fprintf (stderr,
  831. X           "\n<%3d,%3d> input %d, error %d\n",
  832. X           i, j, bmp[i], error);
  833. X      fprintf (stderr, "Noise {%d,%d} Weights {%d,%d,%d,%d}\n",
  834. X           smnoise, lgnoise, w1, w3, w5, w7);
  835. X      fprintf (stderr,
  836. X           "Errs:\t%5d  %5d  %5d\n\t%5d      *\n",
  837. X           eerr[i-1], eerr[i], eerr[i+1], oerr[i-1]);
  838. X    }
  839. X# endif
  840. X
  841. X    if (gray > (WHITE/2))
  842. X    { obm[i] = 1;    oerr[i] = gray - WHITE; }
  843. X    else
  844. X    { obm[i] = 0;    oerr[i] = gray; }
  845. X      }
  846. X      
  847. X      /* Set errors for ends of this row */
  848. X      oerr[0]   = INITERR (bmp[0], obm[0]);
  849. X      oerr[w-1] = INITERR (bmp[w-1], obm[w-1]);
  850. X    }
  851. X    else
  852. X    { eerr[w-1] = INITERR (bmp[w-1], obm[w-1]);
  853. X
  854. X      for (i=w-2; i>0; i--)
  855. X      { /* Set random weights */
  856. X    w1 = 1000; w3 = 3000; w5 = 5000; w7 = 7000;
  857. X  
  858. X    smnoise = RAND (smrange) - smrange/2;
  859. X    w1 += smnoise; w3 -= smnoise;
  860. X  
  861. X    lgnoise = RAND (lgrange) - lgrange/2;
  862. X    w5 += lgnoise; w7 -= lgnoise;
  863. X  
  864. X    error =  (w1 * oerr[i+1] +
  865. X          w5 * oerr[i] +
  866. X          w3 * oerr[i-1] +
  867. X          w7 * eerr[i+1]) / 16000;
  868. X    gray = bmp[i] + error;
  869. X  
  870. X    if (gray > (WHITE/2))
  871. X    { obm[i] = 1;    eerr[i] = gray - WHITE; }
  872. X    else
  873. X    { obm[i] = 0;    eerr[i] = gray; }
  874. X      }
  875. X
  876. X      /* Set errors for ends of this row */
  877. X      eerr[0]   = INITERR (bmp[0], obm[0]);
  878. X      eerr[w-1] = INITERR (bmp[w-1], obm[w-1]);
  879. X    }
  880. X  }
  881. X  return (1);
  882. X}
  883. END_OF_FILE
  884. if test 5880 -ne `wc -c <'flblue.c'`; then
  885.     echo shar: \"'flblue.c'\" unpacked with wrong size!
  886. fi
  887. # end of 'flblue.c'
  888. fi
  889. if test -f 'flextr.c' -a "${1}" != "-c" ; then 
  890.   echo shar: Will not clobber existing file \"'flextr.c'\"
  891. else
  892. echo shar: Extracting \"'flextr.c'\" \(5644 characters\)
  893. sed "s/^X//" >'flextr.c' <<'END_OF_FILE'
  894. X/*****************************************************************
  895. X * flextr.c: FBM Library 0.9 (Beta test) 07-Mar-89  Michael Mauldin
  896. X *
  897. X * Copyright (C) 1989 by Michael Mauldin.  Permission is granted to
  898. X * use this file in whole or in part provided that you do not sell it
  899. X * for profit and that this copyright notice is retained unchanged.
  900. X *
  901. X * flextr.c: Extract a rectangle and/or resize it.
  902. X *
  903. X * CONTENTS
  904. X *    extract_fbm (input, output, xo, yo, w, h, ow, oh, title, credits)
  905. X *
  906. X * EDITLOG
  907. X *    LastEditDate = Tue Mar  7 19:56:56 1989 - Michael Mauldin
  908. X *    LastFileName = /usr2/mlm/src/misc/fbm/flextr.c
  909. X *
  910. X * HISTORY
  911. X * 07-Mar-89  Michael Mauldin (mlm) at Carnegie Mellon University
  912. X *    Beta release (version 0.9) mlm@cs.cmu.edu
  913. X *
  914. X * 12-Nov-88  Michael Mauldin (mlm) at Carnegie-Mellon University
  915. X *    Created.
  916. X *****************************************************************/
  917. X
  918. X# include <stdio.h>
  919. X# include <math.h>
  920. X# include <ctype.h>
  921. X# include "fbm.h"
  922. X
  923. X/****************************************************************
  924. X * extract_fbm: Resize a bitmap
  925. X *    copy input [xo:xo+w yo:yo+h] to output [ow oh]
  926. X ****************************************************************/
  927. X
  928. X#ifndef lint
  929. Xstatic char *fbmid =
  930. X    "$FBM flextr.c <0.9> 07-Mar-89  (C) 1989 by Michael Mauldin$";
  931. X#endif
  932. X
  933. Xextract_fbm (input, output, xo, yo, w, h, ow, oh, title, credits)
  934. XFBM *input, *output;
  935. Xint xo, yo, h, w, oh, ow;
  936. Xchar *title, *credits;
  937. X{ int k, rowlen;
  938. X
  939. X  if ((w != ow || h != oh) && input->hdr.bits != 8)
  940. X  { fprintf (stderr,
  941. X         "Can't resize images with %d bits per pixel\n", input->hdr.bits);
  942. X    return (0);
  943. X  }
  944. X
  945. X  if (input->hdr.physbits != 8)
  946. X  { fprintf (stderr,
  947. X         "Can't extract images with %d physbits per pixel\n",
  948. X         input->hdr.physbits);
  949. X    return (0);
  950. X  }
  951. X
  952. X  if (h < 1 || w < 1 || oh < 1 || ow < 1)
  953. X  { fprintf (stderr, "Extract: zero dimension [%dx%d] => [%dx%d]\n", 
  954. X         w, h, ow, oh);
  955. X    return (0);
  956. X  }
  957. X
  958. X  fprintf (stderr,
  959. X       "Extract \"%s\" <%d,%d> [%dx%d] => [%dx%d] %d pixels\n",
  960. X       title ? title : input->hdr.title ? input->hdr.title : "untitled",
  961. X       xo, yo, w, h, ow, oh, ow*oh);
  962. X
  963. X  if (xo+w > input->hdr.cols)
  964. X  { fprintf (stderr, "Warning, input exceeds image horizontally\n");
  965. X    fprintf (stderr, "    xo %d, w %d, input->hdr.cols %d\n",
  966. X         xo, w, input->hdr.cols);
  967. X  }
  968. X  if (yo+h > input->hdr.rows)
  969. X  { fprintf (stderr, "Warning, input exceeds image vertically\n");
  970. X    fprintf (stderr, "    yo %d, h %d, input->hdr.rows %d\n",
  971. X         yo, h, input->hdr.rows);
  972. X  }
  973. X
  974. X  /* Calculate length of row (pad to even byte boundary) */
  975. X  rowlen = 2 * ((ow * input->hdr.physbits + 15) / 16);
  976. X  
  977. X  /* Now build header for output bit map */
  978. X  output->hdr.cols = ow;
  979. X  output->hdr.rows = oh;
  980. X  output->hdr.planes = input->hdr.planes;
  981. X  output->hdr.bits = input->hdr.bits;
  982. X  output->hdr.physbits = input->hdr.physbits;
  983. X  output->hdr.rowlen = rowlen;
  984. X  output->hdr.plnlen = oh * output->hdr.rowlen;
  985. X  output->hdr.clrlen = input->hdr.clrlen;
  986. X  output->hdr.aspect = input->hdr.aspect * ow * h / (oh * w);
  987. X
  988. X  if (title == NULL || *title == '\0')
  989. X  { strncpy (output->hdr.title, input->hdr.title, FBM_MAX_TITLE); }
  990. X  else
  991. X  { strcpy (output->hdr.title, title); }
  992. X    
  993. X  if (credits == NULL || *credits == '\0')
  994. X  { strncpy (output->hdr.credits, input->hdr.credits, FBM_MAX_TITLE); }
  995. X  else
  996. X  { strcpy (output->hdr.credits, credits); }
  997. X    
  998. X  /* Allocate space for output bits */
  999. X  alloc_fbm (output);
  1000. X
  1001. X  copy_clr (input, output);
  1002. X
  1003. X  /* Now extract each plane separately */
  1004. X  for (k=0; k<output->hdr.planes; k++)
  1005. X  { if (! extract_one (&(input->bm[k * input->hdr.plnlen]),
  1006. X               &(output->bm[k * output->hdr.plnlen]),
  1007. X               input->hdr.cols, input->hdr.rows,
  1008. X               input->hdr.rowlen, output->hdr.rowlen,
  1009. X               xo, yo, w, h, ow, oh))
  1010. X    { free_fbm (output); return (0); }
  1011. X  }
  1012. X
  1013. X  return (1);
  1014. X}
  1015. X
  1016. X/****************************************************************
  1017. X * extract_one: Resize a bitmap
  1018. X *    copy input [xo:xo+w yo:yo+h] to output [ow oh]
  1019. X ****************************************************************/
  1020. X
  1021. Xextract_one (inbm, outbm, cols, rows, inlen, outlen, xo, yo, w, h, ow, oh)
  1022. Xunsigned char *inbm, *outbm;
  1023. Xint inlen, outlen, xo, yo, h, w, oh, ow;
  1024. X{ register int xf, yf, xi, i; 
  1025. X  register unsigned char *bm1, *bm2,  *obm;
  1026. X  int j, yi, dc;
  1027. X
  1028. X  /* Check for scale of 1-1, special case for speed */
  1029. X  if (w == ow && h == oh && xo >= 0 && yo >= 0 && xo+w <= cols && yo+h <= rows)
  1030. X  { for (j=0; j<h; j++)
  1031. X    { bm1 = &inbm[(j+yo) * inlen];
  1032. X      obm = &outbm[j * outlen];
  1033. X
  1034. X      for (i=0; i<w; i++)
  1035. X      { obm[i] = bm1[i + xo]; }
  1036. X    }
  1037. X  }
  1038. X  else
  1039. X  {    
  1040. X    for (j = 0; j<oh; j++)
  1041. X    { yi = (j*h / oh) + yo;
  1042. X      yf = (j*h % oh);
  1043. X
  1044. X      obm = &outbm[j * outlen];
  1045. X      bm1 = &inbm[yi * inlen];
  1046. X      bm2 = bm1 + inlen;
  1047. X
  1048. X      for (i=0; i<ow; i++)
  1049. X      { xi = (i*w / ow) + xo;
  1050. X        xf = (i*w % ow);
  1051. X
  1052. X    if (xi < 0 || yi < 0 ||
  1053. X        xi > cols-2 ||
  1054. X        yi > rows-2)
  1055. X    { static cntr = 0;
  1056. X
  1057. X      /* If right on edge, just use edge value */
  1058. X      if ((xi == cols-1 &&
  1059. X           yi >= 0 && yi <= rows-1) ||
  1060. X          (yi == rows-1 &&
  1061. X           xi >= 0 && xi <= cols-1))
  1062. X      { obm[i] = bm1[xi]; }
  1063. X      else
  1064. X      { obm[i] = 255;
  1065. X
  1066. X        if (cntr++ < 3)
  1067. X        { fprintf (stderr,
  1068. X               "i,j %d,%d => xi,yi %d,%d, out of bounds %d,%d\n",
  1069. X               i, j, xi, yi, cols, rows);
  1070. X          fprintf (stderr,
  1071. X               "w %d, h %d, ow %d, oh %d\n\n", 
  1072. X               w, h, ow, oh);
  1073. X        }  
  1074. X      }
  1075. X        }
  1076. X    else
  1077. X    { dc = ( bm1[xi]   * (ow-xf)*(oh-yf) + 
  1078. X         bm2[xi]   * (ow-xf)*(yf) + 
  1079. X         bm1[xi+1] * (xf)*(oh-yf) + 
  1080. X         bm2[xi+1] * (xf)*(yf) ) / (ow*oh);
  1081. X
  1082. X      if (dc < 0)        { dc = 0; }
  1083. X      else if (dc > 255)    { dc = 255; }
  1084. X
  1085. X      obm[i] = dc;
  1086. X    }
  1087. X      }
  1088. X    }
  1089. X  }
  1090. X
  1091. X  return (1);
  1092. X}
  1093. END_OF_FILE
  1094. if test 5644 -ne `wc -c <'flextr.c'`; then
  1095.     echo shar: \"'flextr.c'\" unpacked with wrong size!
  1096. fi
  1097. # end of 'flextr.c'
  1098. fi
  1099. if test -f 'flgife.c' -a "${1}" != "-c" ; then 
  1100.   echo shar: Will not clobber existing file \"'flgife.c'\"
  1101. else
  1102. echo shar: Extracting \"'flgife.c'\" \(5443 characters\)
  1103. sed "s/^X//" >'flgife.c' <<'END_OF_FILE'
  1104. X/*****************************************************************
  1105. X * flgife.c: FBM Library 0.9 (Beta test) 07-Mar-89  Michael Mauldin
  1106. X *
  1107. X * Portions of this code Copyright (C) 1989 by Michael Mauldin.
  1108. X * Permission is granted to use this file in whole or in part provided
  1109. X * that you do not sell it for profit and that this copyright notice
  1110. X * and the names of all authors are retained unchanged.
  1111. X *
  1112. X * flgife.c:
  1113. X *
  1114. X * CONTENTS
  1115. X *    GIFEncode( wfile, GHeight, GWidth, GInterlace, Background, 
  1116. X *           BitsPerPixel, Red, Green, Blue, GetPixel )
  1117. X *
  1118. X * HISTORY
  1119. X * 07-Mar-89  Michael Mauldin (mlm) at Carnegie Mellon University
  1120. X *    Beta release (version 0.9) mlm@cs.cmu.edu
  1121. X *
  1122. X * 19-Feb-89  Michael Mauldin (mlm) at Carnegie Mellon University
  1123. X *    Adapted to FBM package.  Now takes FILE pointer instead of
  1124. X *    character name for output file.
  1125. X *
  1126. X * 13-Feb-89  David Rowley (mgardi@watdcsu.waterloo.edu)
  1127. X *    Created (sent by mail on 2/13/89)
  1128. X *    original name: GIFENCODE.C - GIF Image compression interface
  1129. X *
  1130. X *****************************************************************************/
  1131. X#include <stdio.h>
  1132. X
  1133. X/*
  1134. X * Pointer to function returning an int
  1135. X */
  1136. Xtypedef int (* ifunptr)();
  1137. X
  1138. X#define TRUE 1
  1139. X#define FALSE 0
  1140. X
  1141. Xstatic int Width, Height;
  1142. Xstatic int curx, cury;
  1143. Xstatic long CountDown;
  1144. Xstatic int Pass = 0;
  1145. Xstatic int Interlace;
  1146. X
  1147. X#ifndef lint
  1148. Xstatic char *fbmid =
  1149. X    "$FBM flgife.c <0.9> 07-Mar-89  (C) 1989 by Michael Mauldin$";
  1150. X#endif
  1151. X
  1152. X
  1153. X/*
  1154. X * Bump the 'curx' and 'cury' to point to the next pixel
  1155. X */
  1156. Xstatic
  1157. XBumpPixel()
  1158. X{
  1159. X    /*
  1160. X     * Bump the current X position
  1161. X     */
  1162. X    curx++;
  1163. X
  1164. X    /*
  1165. X     * If we are at the end of a scan line, set curx back to the beginning
  1166. X     * If we are interlaced, bump the cury to the appropriate spot,
  1167. X     * otherwise, just increment it.
  1168. X     */
  1169. X    if( curx == Width ) {
  1170. X        curx = 0;
  1171. X
  1172. X            if( !Interlace ) 
  1173. X            cury++;
  1174. X        else {
  1175. X             switch( Pass ) {
  1176. X         
  1177. X                   case 0:
  1178. X                      cury += 8;
  1179. X                      if( cury >= Height ) {
  1180. X                  Pass++;
  1181. X                cury = 4;
  1182. X                }
  1183. X                          break;
  1184. X          
  1185. X                   case 1:
  1186. X                      cury += 8;
  1187. X                      if( cury >= Height ) {
  1188. X                  Pass++;
  1189. X                cury = 2;
  1190. X                }
  1191. X              break;
  1192. X          
  1193. X                   case 2:
  1194. X                      cury += 4;
  1195. X                      if( cury >= Height ) {
  1196. X                         Pass++;
  1197. X                         cury = 1;
  1198. X                      }
  1199. X                      break;
  1200. X              
  1201. X                   case 3:
  1202. X                      cury += 2;
  1203. X                      break;
  1204. X            }
  1205. X        }
  1206. X    }
  1207. X}
  1208. X
  1209. X/*
  1210. X * Return the next pixel from the image
  1211. X */
  1212. XGIFNextPixel( getpixel )
  1213. Xifunptr getpixel;
  1214. X{
  1215. X    int r;
  1216. X
  1217. X    if( CountDown == 0 )
  1218. X        return EOF;
  1219. X
  1220. X    CountDown--;
  1221. X
  1222. X    r = ( * getpixel )( curx, cury );
  1223. X
  1224. X    BumpPixel();
  1225. X
  1226. X    return r;
  1227. X}
  1228. X
  1229. X/* public */
  1230. X
  1231. XGIFEncode( wfile, GWidth, GHeight, GInterlace, Background, 
  1232. X       BitsPerPixel, Red, Green, Blue, GetPixel )
  1233. X     
  1234. XFILE *wfile;
  1235. Xint GWidth, GHeight;
  1236. Xint GInterlace;
  1237. Xint Background;
  1238. Xint BitsPerPixel;
  1239. Xint Red[], Green[], Blue[];
  1240. Xifunptr GetPixel;
  1241. X
  1242. X{
  1243. X    FILE *fp;
  1244. X    int B;
  1245. X    int RWidth, RHeight;
  1246. X    int LeftOfs, TopOfs;
  1247. X    int Resolution;
  1248. X    int ColorMapSize;
  1249. X    int InitCodeSize;
  1250. X    int i;
  1251. X
  1252. X    Interlace = GInterlace;
  1253. X    
  1254. X    ColorMapSize = 1 << BitsPerPixel;
  1255. X    
  1256. X    RWidth = Width = GWidth;
  1257. X    RHeight = Height = GHeight;
  1258. X    LeftOfs = TopOfs = 0;
  1259. X    
  1260. X    Resolution = BitsPerPixel;
  1261. X
  1262. X    /*
  1263. X     * Calculate number of bits we are expecting
  1264. X     */
  1265. X    CountDown = (long)Width * (long)Height;
  1266. X
  1267. X    /*
  1268. X     * Indicate which pass we are on (if interlace)
  1269. X     */
  1270. X    Pass = 0;
  1271. X
  1272. X    /*
  1273. X     * The initial code size
  1274. X     */
  1275. X    if( BitsPerPixel <= 1 )
  1276. X        InitCodeSize = 2;
  1277. X    else
  1278. X        InitCodeSize = BitsPerPixel;
  1279. X
  1280. X    /*
  1281. X     * Set up the current x and y position
  1282. X     */
  1283. X    curx = cury = 0;
  1284. X
  1285. X    /*
  1286. X     * Open the GIF file for binary write
  1287. X     */
  1288. X    /* fp = fopen( FName, "wb" ); */
  1289. X
  1290. X    fp = wfile;    /* Change for FBM - mlm 2/19/89 */
  1291. X
  1292. X    if( fp == (FILE *)0 ) {
  1293. X        printf( "error: could not open output file\n" );
  1294. X        return (0);
  1295. X    }
  1296. X
  1297. X    /*
  1298. X     * Write the Magic header
  1299. X     */
  1300. X    fwrite( "GIF87a", 1, 6, fp );
  1301. X
  1302. X    /*
  1303. X     * Write out the screen width and height
  1304. X     */
  1305. X    Putword( RWidth, fp );
  1306. X    Putword( RHeight, fp );
  1307. X
  1308. X    /*
  1309. X     * Indicate that there is a global colour map
  1310. X     */
  1311. X    B = 0x80;    /* Yes, there is a color map */
  1312. X
  1313. X    /*
  1314. X     * OR in the resolution
  1315. X     */
  1316. X    B |= (Resolution - 1) << 5;
  1317. X
  1318. X    /*
  1319. X     * OR in the Bits per Pixel
  1320. X     */
  1321. X    B |= (BitsPerPixel - 1);
  1322. X
  1323. X    /*
  1324. X     * Write it out
  1325. X     */
  1326. X    fputc( B, fp );
  1327. X
  1328. X    /*
  1329. X     * Write out the Background colour
  1330. X     */
  1331. X    fputc( Background, fp );
  1332. X
  1333. X    /*
  1334. X     * Byte of 0s (future expansion)
  1335. X     */
  1336. X    fputc( 0, fp );
  1337. X
  1338. X    /*
  1339. X     * Write out the Global Colour Map
  1340. X     */
  1341. X         for( i=0; i<ColorMapSize; i++ ) {
  1342. X        fputc( Red[i], fp );
  1343. X        fputc( Green[i], fp );
  1344. X        fputc( Blue[i], fp );
  1345. X    }
  1346. X
  1347. X    /*
  1348. X     * Write an Image separator
  1349. X     */
  1350. X    fputc( ',', fp );
  1351. X
  1352. X    /*
  1353. X     * Write the Image header
  1354. X     */
  1355. X
  1356. X    Putword( LeftOfs, fp );
  1357. X    Putword( TopOfs, fp );
  1358. X    Putword( Width, fp );
  1359. X    Putword( Height, fp );
  1360. X
  1361. X    /*
  1362. X     * Write out whether or not the image is interlaced
  1363. X     */
  1364. X    if( Interlace )
  1365. X        fputc( 0x40, fp );
  1366. X    else
  1367. X        fputc( 0x00, fp );
  1368. X
  1369. X    /*
  1370. X     * Write out the initial code size
  1371. X     */
  1372. X    fputc( InitCodeSize, fp );
  1373. X
  1374. X    /*
  1375. X     * Go and actually compress the data
  1376. X     */
  1377. X    compress( InitCodeSize+1, fp, GetPixel );
  1378. X
  1379. X    /*
  1380. X     * Write out a Zero-length packet (to end the series)
  1381. X     */
  1382. X    fputc( 0, fp );
  1383. X
  1384. X    /*
  1385. X     * Write the GIF file terminator
  1386. X     */
  1387. X    fputc( ';', fp );
  1388. X
  1389. X    /*
  1390. X     * And close the file
  1391. X     */
  1392. X    fclose( fp );
  1393. X    
  1394. X    return (1);    /* success - mlm 2/19/89 */
  1395. X}
  1396. X
  1397. X/*
  1398. X * Write out a word to the GIF file
  1399. X */
  1400. Xstatic
  1401. XPutword( w, fp )
  1402. Xint w;
  1403. XFILE *fp;
  1404. X{
  1405. X    fputc( w & 0xff, fp );
  1406. X    fputc( (w / 256) & 0xff, fp );
  1407. X}
  1408. END_OF_FILE
  1409. if test 5443 -ne `wc -c <'flgife.c'`; then
  1410.     echo shar: \"'flgife.c'\" unpacked with wrong size!
  1411. fi
  1412. # end of 'flgife.c'
  1413. fi
  1414. if test -f 'flpbm.c' -a "${1}" != "-c" ; then 
  1415.   echo shar: Will not clobber existing file \"'flpbm.c'\"
  1416. else
  1417. echo shar: Extracting \"'flpbm.c'\" \(5001 characters\)
  1418. sed "s/^X//" >'flpbm.c' <<'END_OF_FILE'
  1419. X/*****************************************************************
  1420. X * flpbm.c: FBM Library 0.9 (Beta test) 07-Mar-89  Michael Mauldin
  1421. X *
  1422. X * Copyright (C) 1989 by Michael Mauldin.  Permission is granted to
  1423. X * use this file in whole or in part provided that you do not sell it
  1424. X * for profit and that this copyright notice is retained unchanged.
  1425. X *
  1426. X * flpbm.c: 
  1427. X *
  1428. X * CONTENTS
  1429. X *    read_pbm (image, infile, mstr, mlen)
  1430. X *    write_pbm (image, stream)
  1431. X *
  1432. X * EDITLOG
  1433. X *    LastEditDate = Tue Mar  7 19:57:22 1989 - Michael Mauldin
  1434. X *    LastFileName = /usr2/mlm/src/misc/fbm/flpbm.c
  1435. X *
  1436. X * HISTORY
  1437. X * 07-Mar-89  Michael Mauldin (mlm) at Carnegie Mellon University
  1438. X *    Beta release (version 0.9) mlm@cs.cmu.edu
  1439. X *
  1440. X * 12-Nov-88  Michael Mauldin (mlm) at Carnegie-Mellon University
  1441. X *    Created.
  1442. X *****************************************************************/
  1443. X
  1444. X# include <stdio.h>
  1445. X# include <math.h>
  1446. X# include <ctype.h>
  1447. X# include "fbm.h"
  1448. X
  1449. X/****************************************************************
  1450. X * read_pbm: Read a pbm file into an fbm bitmap
  1451. X ****************************************************************/
  1452. X
  1453. X#ifndef lint
  1454. Xstatic char *fbmid =
  1455. X    "$FBM flpbm.c <0.9> 07-Mar-89  (C) 1989 by Michael Mauldin$";
  1456. X#endif
  1457. X
  1458. Xread_pbm (image, infile, mstr, mlen)
  1459. XFBM *image;
  1460. XFILE *infile;
  1461. Xchar *mstr;
  1462. Xint mlen;
  1463. X{ register int ch, i, j;
  1464. X  register unsigned char *bmp;
  1465. X  char cmtbuf[128], *s;
  1466. X
  1467. X  if ((ch = NEXTMCH (infile, mstr, mlen)) != 'P' || 
  1468. X      (ch = NEXTMCH (infile, mstr, mlen)) != '1')
  1469. X  { fprintf (stderr, "bad magic number, input not PBM file\n");
  1470. X    return (0);
  1471. X  }
  1472. X
  1473. X  image->hdr.cols = pbm_getint (infile);
  1474. X  image->hdr.rows = pbm_getint (infile);
  1475. X  image->hdr.planes = 1;
  1476. X  image->hdr.bits = 1;  
  1477. X  image->hdr.physbits = 8;
  1478. X  image->hdr.rowlen = 16 * ((image->hdr.cols + 15) / 16);
  1479. X  image->hdr.plnlen = image->hdr.rowlen * image->hdr.rows;
  1480. X  image->hdr.clrlen = 0;
  1481. X  image->hdr.aspect = 1.0;
  1482. X  image->hdr.title[0] = '\0';
  1483. X  
  1484. X  if (image->hdr.cols < 1 || image->hdr.rows < 1)
  1485. X  { fprintf (stderr, "Error, specified size %d by %d\n",
  1486. X         image->hdr.cols, image->hdr.rows);
  1487. X    return (0);
  1488. X  }
  1489. X  
  1490. X  fprintf (stderr,
  1491. X       "Reading PBM file \"%s\" [%dx%dx1]\n",
  1492. X       image->hdr.title[0] ? image->hdr.title : "",
  1493. X       image->hdr.cols, image->hdr.rows);
  1494. X
  1495. X  alloc_fbm (image);
  1496. X
  1497. X  for (j=0; j<image->hdr.rows; j++)
  1498. X  { bmp = &(image->bm[j * image->hdr.rowlen]);
  1499. X
  1500. X    for (i=0; i<image->hdr.cols; i++)
  1501. X    { while ((ch = fgetc (infile)) != EOF)
  1502. X      { if (ch == '0') { *bmp++ = WHITE; break; }
  1503. X
  1504. X        else if (ch == '1') { *bmp++ = BLACK; break; }
  1505. X
  1506. X    else if (ch == '#')
  1507. X        { s = cmtbuf; *s++ = '#';
  1508. X      while ((ch = fgetc (infile)) != EOF && ch != '\n') *s++ = ch;
  1509. X      *s = '\0';
  1510. X      for (s=cmtbuf; *s == '#' || isspace (*s); s++) ;
  1511. X      if (!strncmp (s, "Title: ", 7)) strcpy (image->hdr.title, s+7);
  1512. X      fprintf (stderr, "Read_pbm found title '%s'\n",
  1513. X           image->hdr.title);
  1514. X    }
  1515. X      }
  1516. X      
  1517. X      if (ch == EOF)
  1518. X      { fprintf (stderr, "premature EOF, row %d, col %d\n", j, i);
  1519. X        return (0);
  1520. X      }
  1521. X    }
  1522. X  }
  1523. X
  1524. X  
  1525. X  return (1);
  1526. X}
  1527. X
  1528. X/****************************************************************
  1529. X * pbm_getint: Read a number from a PBM file, ignoring comments
  1530. X ****************************************************************/
  1531. X
  1532. X# define START 1
  1533. X# define COMMENT 2
  1534. X# define INTEGER 3
  1535. X
  1536. Xpbm_getint (infile)
  1537. XFILE *infile;
  1538. X{ char buf[80];
  1539. X  register char *s = buf;
  1540. X  register int ch;
  1541. X  int state = START;
  1542. X
  1543. X  while (1)
  1544. X  { if ((ch = fgetc (infile)) == EOF)
  1545. X    { fprintf (stderr, "premature EOF\n");
  1546. X      return (0);
  1547. X    }
  1548. X
  1549. X    switch (state)
  1550. X    { case START:    if (isspace (ch)) ;
  1551. X            else if (ch == '#') state = COMMENT;
  1552. X            else if (isdigit (ch))
  1553. X            { *s++ = ch; state = INTEGER; }
  1554. X            else
  1555. X            { fprintf (stderr, "bad INTEGER in input");
  1556. X              return (0);
  1557. X            }
  1558. X            break;
  1559. X
  1560. X      case COMMENT:    if (ch == '\n') state = START;
  1561. X            break;
  1562. X
  1563. X      case INTEGER:    if (isdigit (ch)) *s++ = ch;
  1564. X            else
  1565. X            { register int result;
  1566. X
  1567. X              *s = '\0';
  1568. X              result = atoi (buf);
  1569. X              return (result);
  1570. X            }
  1571. X            break;
  1572. X
  1573. X      default:        fprintf (stderr, "impossible state %d\n", state);
  1574. X            return (0);
  1575. X    }
  1576. X  }
  1577. X}
  1578. X
  1579. X/****************************************************************
  1580. X * write_pbm: Write a bitmap in PBM format to the output device
  1581. X ****************************************************************/
  1582. X
  1583. Xwrite_pbm (image, stream)
  1584. Xregister FBM *image;
  1585. XFILE *stream;
  1586. X{ register int i, j, outcol = 0;
  1587. X  register unsigned char *bmp;
  1588. X
  1589. X  /* Write PBM header lines */
  1590. X  fprintf (stream, "P1\n%d %d\n", image->hdr.cols, image->hdr.rows);
  1591. X  if (image->hdr.title[0])
  1592. X  { fprintf (stream, "# Title: %s\n", image->hdr.title); }
  1593. X  
  1594. X  /* Now write out 1s and 0s, in 70 character lines */
  1595. X  for (j=0; j < image->hdr.rows; j++)
  1596. X  { bmp = &(image->bm[j * image->hdr.rowlen]);
  1597. X
  1598. X    for (i=0; i < image->hdr.cols; i++)
  1599. X    { fputc (*bmp++ ? '0' : '1', stream);    /* In PBM 1=black, not white */
  1600. X      if (++outcol >= 70) { fprintf (stream, "\n"); outcol=0; }
  1601. X    }
  1602. X    if (outcol) { fprintf (stream, "\n"); outcol=0; }
  1603. X  }
  1604. X  
  1605. X  return (1);
  1606. X}
  1607. END_OF_FILE
  1608. if test 5001 -ne `wc -c <'flpbm.c'`; then
  1609.     echo shar: \"'flpbm.c'\" unpacked with wrong size!
  1610. fi
  1611. # end of 'flpbm.c'
  1612. fi
  1613. if test -f 'flrot.c' -a "${1}" != "-c" ; then 
  1614.   echo shar: Will not clobber existing file \"'flrot.c'\"
  1615. else
  1616. echo shar: Extracting \"'flrot.c'\" \(5222 characters\)
  1617. sed "s/^X//" >'flrot.c' <<'END_OF_FILE'
  1618. X/*****************************************************************
  1619. X * flrot.c: FBM Library 0.9 (Beta test) 07-Mar-89  Michael Mauldin
  1620. X *
  1621. X * Copyright (C) 1989 by Michael Mauldin.  Permission is granted to
  1622. X * use this file in whole or in part provided that you do not sell it
  1623. X * for profit and that this copyright notice is retained unchanged.
  1624. X *
  1625. X * flrot.c: 
  1626. X *
  1627. X * CONTENTS
  1628. X *    rotate_fbm (input, output, rot)
  1629. X *
  1630. X * EDITLOG
  1631. X *    LastEditDate = Tue Mar  7 19:57:29 1989 - Michael Mauldin
  1632. X *    LastFileName = /usr2/mlm/src/misc/fbm/flrot.c
  1633. X *
  1634. X * HISTORY
  1635. X * 07-Mar-89  Michael Mauldin (mlm) at Carnegie Mellon University
  1636. X *    Beta release (version 0.9) mlm@cs.cmu.edu
  1637. X *
  1638. X * 12-Nov-88  Michael Mauldin (mlm) at Carnegie-Mellon University
  1639. X *    Created.
  1640. X *****************************************************************/
  1641. X
  1642. X# include <stdio.h>
  1643. X# include <math.h>
  1644. X# include <ctype.h>
  1645. X# include "fbm.h"
  1646. X
  1647. X/****************************************************************
  1648. X * rotate_fbm: Rotate input bitmap
  1649. X ****************************************************************/
  1650. X
  1651. X#ifndef lint
  1652. Xstatic char *fbmid =
  1653. X    "$FBM flrot.c <0.9> 07-Mar-89  (C) 1989 by Michael Mauldin$";
  1654. X#endif
  1655. X
  1656. Xrotate_fbm (input, output, rot)
  1657. XFBM *input, *output;
  1658. Xint rot;
  1659. X{
  1660. X  switch (rot)
  1661. X  { case 90:    return (rot90_fbm  (input, output));
  1662. X    case 180:    return (rot180_fbm (input, output));
  1663. X    case 270:    return (rot270_fbm (input, output));
  1664. X    default:    fprintf (stderr, "%s %d degrees, must be 90, 180, or 270\n",
  1665. X             "invalid rotation", rot);
  1666. X        return (0);
  1667. X  }
  1668. X}
  1669. X
  1670. X/****************************************************************
  1671. X * rot90_fbm: Rotate input bitmap 90 degrees clockwise
  1672. X ****************************************************************/
  1673. X
  1674. Xrot90_fbm (input, output)
  1675. XFBM *input, *output;
  1676. X{ register int i, j, k, oi, oj;
  1677. X  int iw, ow, ih, oh, irow, orow, ipln, opln;
  1678. X
  1679. X  if (input->hdr.physbits != 8)
  1680. X  { fprintf (stderr,
  1681. X        "Can't handle images %d physical bits per pixel\n",
  1682. X        input->hdr.physbits);
  1683. X    exit (1);
  1684. X  }
  1685. X
  1686. X  oh = iw = input->hdr.cols;
  1687. X  ow = ih = input->hdr.rows;
  1688. X  
  1689. X  irow = input->hdr.rowlen;
  1690. X  ipln = input->hdr.plnlen;
  1691. X
  1692. X  /* Calculate row length (input height padded to even byte boundary) */
  1693. X  if (input->hdr.bits == 1)
  1694. X  { orow = 16 * ((ow + 15) / 16); }
  1695. X  else
  1696. X  { orow = 2 * ((ow * input->hdr.physbits + 15) / 16); }
  1697. X
  1698. X  opln = orow * oh; 
  1699. X
  1700. X  /* Now build header for output bit map */
  1701. X  output->hdr = input->hdr;
  1702. X  output->hdr.cols = ow;
  1703. X  output->hdr.rows = oh;
  1704. X  output->hdr.rowlen = orow;
  1705. X  output->hdr.plnlen = opln;
  1706. X  output->hdr.aspect = 1.0 / input->hdr.aspect;
  1707. X  
  1708. X  /* Allocate space for output bits */
  1709. X  alloc_fbm (output);
  1710. X  
  1711. X  copy_clr (input, output);
  1712. X
  1713. X  for (k=0; k<output->hdr.planes; k++)
  1714. X  { for (j=0; j<ih; j++)
  1715. X    { for (i=0; i<iw; i++)
  1716. X      { oj = i; oi = ih - (j+1);
  1717. X        output->bm[k*opln + oj*orow + oi] = input->bm[k*ipln + j*irow + i];
  1718. X      }
  1719. X    }
  1720. X  }
  1721. X
  1722. X  return (1);
  1723. X}
  1724. X
  1725. X/****************************************************************
  1726. X * rot180_fbm: Rotate input bitmap 180 degrees clockwise
  1727. X ****************************************************************/
  1728. X
  1729. Xrot180_fbm (input, output)
  1730. XFBM *input, *output;
  1731. X{ register int i, j, k, oi, oj;
  1732. X  int w, h, row, pln;
  1733. X
  1734. X  if (input->hdr.physbits != 8)
  1735. X  { fprintf (stderr,
  1736. X         "Can't handle images %d physical bits per pixel\n",
  1737. X         input->hdr.physbits);
  1738. X    exit (1);
  1739. X  }
  1740. X
  1741. X  /* Now build header for output bit map */
  1742. X  output->hdr = input->hdr;
  1743. X  w = input->hdr.cols;
  1744. X  h = input->hdr.rows;
  1745. X  row = input->hdr.rowlen;
  1746. X  pln = input->hdr.plnlen;
  1747. X  
  1748. X  /* Allocate space for output bits */
  1749. X  alloc_fbm (output);
  1750. X  
  1751. X  copy_clr (input, output);
  1752. X
  1753. X  for (k=0; k<output->hdr.planes; k++)
  1754. X  { for (j=0; j<h; j++)
  1755. X    { for (i=0; i<w; i++)
  1756. X      { oj = h - (j+1); oi = w - (i+1);
  1757. X        output->bm[k*pln + oj*row + oi] = input->bm[k*pln + j*row + i];
  1758. X      }
  1759. X    }
  1760. X  }
  1761. X
  1762. X  return (1);
  1763. X}
  1764. X
  1765. X/****************************************************************
  1766. X * rot270_fbm: Rotate input bitmap 270 degrees clockwise
  1767. X ****************************************************************/
  1768. X
  1769. Xrot270_fbm (input, output)
  1770. XFBM *input, *output;
  1771. X{ register int i, j, k, oi, oj;
  1772. X  int iw, ow, ih, oh, irow, orow, ipln, opln;
  1773. X
  1774. X  if (input->hdr.physbits != 8)
  1775. X  { fprintf (stderr,
  1776. X        "Can't handle images %d physical bits per pixel\n",
  1777. X        input->hdr.physbits);
  1778. X    exit (1);
  1779. X  }
  1780. X
  1781. X  oh = iw = input->hdr.cols;
  1782. X  ow = ih = input->hdr.rows;
  1783. X  
  1784. X  irow = input->hdr.rowlen;
  1785. X  ipln = input->hdr.plnlen;
  1786. X
  1787. X  /* Calculate row length (input height padded to even byte boundary) */
  1788. X  if (input->hdr.bits == 1)
  1789. X  { orow = 16 * ((ow + 15) / 16); }
  1790. X  else
  1791. X  { orow = 2 * ((ow * input->hdr.physbits + 15) / 16); }
  1792. X
  1793. X  opln = orow * oh;
  1794. X  
  1795. X  /* Now build header for output bit map */
  1796. X  output->hdr = input->hdr;
  1797. X  output->hdr.cols = ow;
  1798. X  output->hdr.rows = oh;
  1799. X  output->hdr.rowlen = orow;
  1800. X  output->hdr.plnlen = opln;
  1801. X  output->hdr.aspect = 1.0 / input->hdr.aspect;
  1802. X  
  1803. X  /* Allocate space for output bits */
  1804. X  alloc_fbm (output);
  1805. X  
  1806. X  copy_clr (input, output);
  1807. X
  1808. X  for (k=0; k<output->hdr.planes; k++)
  1809. X  { for (j=0; j<ih; j++)
  1810. X    { for (i=0; i<iw; i++)
  1811. X      { oj = iw - (i+1); oi = j;
  1812. X        output->bm[k*opln + oj*orow + oi] = input->bm[k*ipln + j*irow + i];
  1813. X      }
  1814. X    }
  1815. X  }
  1816. X
  1817. X  return (1);
  1818. X}
  1819. END_OF_FILE
  1820. if test 5222 -ne `wc -c <'flrot.c'`; then
  1821.     echo shar: \"'flrot.c'\" unpacked with wrong size!
  1822. fi
  1823. # end of 'flrot.c'
  1824. fi
  1825. if test -f 'flshrp.c' -a "${1}" != "-c" ; then 
  1826.   echo shar: Will not clobber existing file \"'flshrp.c'\"
  1827. else
  1828. echo shar: Extracting \"'flshrp.c'\" \(5370 characters\)
  1829. sed "s/^X//" >'flshrp.c' <<'END_OF_FILE'
  1830. X/*****************************************************************
  1831. X * flshrp.c: FBM Library 0.9 (Beta test) 07-Mar-89  Michael Mauldin
  1832. X *
  1833. X * Copyright (C) 1989 by Michael Mauldin.  Permission is granted to
  1834. X * use this file in whole or in part provided that you do not sell it
  1835. X * for profit and that this copyright notice is retained unchanged.
  1836. X *
  1837. X * flshrp.c: 
  1838. X *
  1839. X * CONTENTS
  1840. X *    sharpen_fbm (input, output, beta)
  1841. X *
  1842. X * EDITLOG
  1843. X *    LastEditDate = Tue Mar  7 19:57:30 1989 - Michael Mauldin
  1844. X *    LastFileName = /usr2/mlm/src/misc/fbm/flshrp.c
  1845. X *
  1846. X * HISTORY
  1847. X * 07-Mar-89  Michael Mauldin (mlm) at Carnegie Mellon University
  1848. X *    Beta release (version 0.9) mlm@cs.cmu.edu
  1849. X *
  1850. X * 12-Nov-88  Michael Mauldin (mlm) at Carnegie-Mellon University
  1851. X *    Created.
  1852. X *****************************************************************/
  1853. X
  1854. X# include <stdio.h>
  1855. X# include <math.h>
  1856. X# include <ctype.h>
  1857. X# include "fbm.h"
  1858. X
  1859. X/****************************************************************
  1860. X * sharpen_fbm: determine whether image is in color, and call the
  1861. X *            appropriate sharpening routine.
  1862. X ****************************************************************/
  1863. X
  1864. X#ifndef lint
  1865. Xstatic char *fbmid =
  1866. X    "$FBM flshrp.c <0.9> 07-Mar-89  (C) 1989 by Michael Mauldin$";
  1867. X#endif
  1868. X
  1869. Xsharpen_fbm (input, output, beta)
  1870. XFBM *input, *output;
  1871. Xdouble beta;
  1872. X{
  1873. X  if (input->hdr.planes == 1 && input->hdr.clrlen == 0)
  1874. X  { return (sharpen_bw (input, output, beta)); }
  1875. X  else
  1876. X  { return (sharpen_clr (input, output, beta)); }
  1877. X}
  1878. X
  1879. X/****************************************************************
  1880. X * sharpen_bw: use a digital Laplacian filter to sharpen a BW image
  1881. X ****************************************************************/
  1882. X
  1883. Xsharpen_bw (input, output, beta)
  1884. XFBM *input, *output;
  1885. Xdouble beta;
  1886. X{ register unsigned char *bmp, *obm;
  1887. X  register int i, j, rowlen, w, h, sum;
  1888. X  int new, delta, beta100 = beta * 100;
  1889. X
  1890. X  if (input->hdr.planes != 1)
  1891. X  { fprintf (stderr, "sharpen_bw: can't sharpen color images\n");
  1892. X    return (0);
  1893. X  }
  1894. X
  1895. X  fprintf (stderr, "Sharpen BW, beta %lg\n", beta);
  1896. X
  1897. X  /* Allocate output */
  1898. X  output->hdr = input->hdr;
  1899. X  alloc_fbm (output);
  1900. X
  1901. X  w = input->hdr.cols;
  1902. X  h = input->hdr.rows;
  1903. X  rowlen = input->hdr.rowlen;
  1904. X
  1905. X  /* Copy edges directly */
  1906. X  for (j=0; j<h; j++)
  1907. X  { output->bm[j*rowlen] = input->bm[j*rowlen];
  1908. X    output->bm[j*rowlen + w-1] = input->bm[j*rowlen + w-1];
  1909. X  }
  1910. X
  1911. X  for (i=0; i<w; i++)
  1912. X  { output->bm[i] = input->bm[i];
  1913. X    output->bm[(h-1)*rowlen + i] = input->bm[(h-1)*rowlen + i];
  1914. X  }
  1915. X
  1916. X  for (j=1; j < h-1; j++)
  1917. X  { bmp = &(input->bm[j*rowlen]);
  1918. X    obm = &(output->bm[j*rowlen]);
  1919. X    
  1920. X    for (i=1; i < w-1; i++)
  1921. X    { sum = bmp[i-rowlen-1] +     bmp[i-rowlen] + bmp[i-rowlen+1] +
  1922. X        bmp[i-1]        - 8 * bmp[i]        + bmp[i+1]        +
  1923. X        bmp[i+rowlen-1] +     bmp[i+rowlen] + bmp[i+rowlen+1];
  1924. X
  1925. X      if (sum < 0)
  1926. X      { delta = - (beta100 * bmp[i] * -sum / (8*WHITE*100)); }
  1927. X      else
  1928. X      { delta = beta100 * bmp[i] * sum / (8*WHITE*100); }
  1929. X
  1930. X      new = bmp[i] - delta;
  1931. X
  1932. X      if (new < BLACK) new = BLACK;
  1933. X      else if (new > WHITE) new = WHITE;
  1934. X      
  1935. X      obm[i] = new;
  1936. X    }
  1937. X  }
  1938. X  
  1939. X  return (1);
  1940. X}
  1941. X
  1942. X/****************************************************************
  1943. X * sharpen_clr: use a digital Laplacian filter to sharpen a CLR image
  1944. X ****************************************************************/
  1945. X
  1946. Xsharpen_clr (input, output, beta)
  1947. XFBM *input, *output;
  1948. Xdouble beta;
  1949. X{ register unsigned char *bmp, *obm, *avg;
  1950. X  register int i, j, k, rowlen, plnlen, w, h, p, sum;
  1951. X  int new, delta, beta100 = beta * 100;
  1952. X  unsigned char *gray;
  1953. X
  1954. X  if (input->hdr.clrlen > 0)
  1955. X  { fprintf (stderr,
  1956. X     "cannot sharpen mapped color images, use 'gray2clr -u' first\n");
  1957. X    return (0);
  1958. X  }
  1959. X
  1960. X  fprintf (stderr, "Sharpen color, beta %lg\n", beta);
  1961. X
  1962. X  /* Allocate output */
  1963. X  output->hdr = input->hdr;
  1964. X  alloc_fbm (output);
  1965. X
  1966. X  w = input->hdr.cols;
  1967. X  h = input->hdr.rows;
  1968. X  p = input->hdr.planes;
  1969. X  rowlen = input->hdr.rowlen;
  1970. X  plnlen = input->hdr.plnlen;
  1971. X  
  1972. X  /* Calculate the intensity plane */
  1973. X  gray = (unsigned char *) malloc (plnlen);
  1974. X
  1975. X  for (j=0; j<h; j++)  
  1976. X  { bmp = &(input->bm[j*rowlen]);
  1977. X    avg = &(gray[j*rowlen]);    
  1978. X
  1979. X    for (i=0; i<w; i++)
  1980. X    { sum = 0;
  1981. X      for (k=0; k<p; k++)
  1982. X      { sum += bmp[i+k*plnlen]; }
  1983. X      avg[i] = sum/p;
  1984. X    }
  1985. X  }
  1986. X  
  1987. X  /* Copy edges directly */
  1988. X  for (k=0; k<p; k++)
  1989. X  {  for (j=0; j<h; j++)
  1990. X    { output->bm[k*plnlen + j*rowlen] =
  1991. X    input->bm[k*plnlen + j*rowlen];
  1992. X      output->bm[k*plnlen + j*rowlen + w-1] =
  1993. X    input->bm[k*plnlen + j*rowlen + w-1];
  1994. X    }
  1995. X  
  1996. X    for (i=0; i<w; i++)
  1997. X    { output->bm[k*plnlen + i] =
  1998. X    input->bm[k*plnlen + i];
  1999. X      output->bm[k*plnlen + (h-1)*rowlen + i] =
  2000. X    input->bm[k*plnlen + (h-1)*rowlen + i];
  2001. X    }
  2002. X  }
  2003. X
  2004. X  for (j=1; j < h-1; j++)
  2005. X  { avg = &(gray[j*rowlen]);
  2006. X    
  2007. X    for (i=1; i < w-1; i++)
  2008. X    { sum = avg[i-rowlen-1] +     avg[i-rowlen] + avg[i-rowlen+1] +
  2009. X        avg[i-1]        - 8 * avg[i]        + avg[i+1]        +
  2010. X        avg[i+rowlen-1] +     avg[i+rowlen] + avg[i+rowlen+1];
  2011. X
  2012. X      for (k=0; k<p; k++)
  2013. X      { bmp =  &(input->bm[k*plnlen + j*rowlen + i]);
  2014. X        obm = &(output->bm[k*plnlen + j*rowlen + i]);
  2015. X        
  2016. X    if (sum < 0)
  2017. X    { delta = - (beta100 * *bmp * -sum / (8*WHITE*100)); }
  2018. X    else
  2019. X    { delta = beta100 * *bmp * sum / (8*WHITE*100); }
  2020. X  
  2021. X    new = *bmp - delta;
  2022. X  
  2023. X    if (new < BLACK) new = BLACK;
  2024. X    else if (new > WHITE) new = WHITE;
  2025. X    
  2026. X    *obm = new;
  2027. X      }
  2028. X    }
  2029. X  }
  2030. X  
  2031. X  return (1);
  2032. X}
  2033. END_OF_FILE
  2034. if test 5370 -ne `wc -c <'flshrp.c'`; then
  2035.     echo shar: \"'flshrp.c'\" unpacked with wrong size!
  2036. fi
  2037. # end of 'flshrp.c'
  2038. fi
  2039. echo shar: End of archive 4 \(of 8\).
  2040. cp /dev/null ark4isdone
  2041. MISSING=""
  2042. for I in 1 2 3 4 5 6 7 8 ; do
  2043.     if test ! -f ark${I}isdone ; then
  2044.     MISSING="${MISSING} ${I}"
  2045.     fi
  2046. done
  2047. if test "${MISSING}" = "" ; then
  2048.     echo You have unpacked all 8 archives.
  2049.     rm -f ark[1-9]isdone
  2050. else
  2051.     echo You still need to unpack the following archives:
  2052.     echo "        " ${MISSING}
  2053. fi
  2054. ##  End of shell archive.
  2055. exit 0
  2056.